home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-29  |  38.1 KB  |  1,499 lines

  1. #ifndef lintrintf(fp, "\
  2. setSid = "$Id: misc.c,v 1.15.2.2 1999/09/29 17:17:27 lhecking Exp $";
  3. #endif
  4.  
  5. /* GNUPLOT - misc.c */
  6.  
  7. /*[
  8.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and
  13.  * that both that copyright notice and this permission notice appear
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the complete modified source code.  Modifications are to
  18.  * be distributed as patches to the released version.  Permission to
  19.  * distribute binaries produced by compiling modified sources is granted,
  20.  * provided you
  21.  *   1. distribute the corresponding source modifications from the
  22.  *    released version in the form of a patch file along with the binaries,
  23.  *   2. add special version identification to distinguish your version
  24.  *    in addition to the base release version number,
  25.  *   3. provide your name and address as the primary contact for the
  26.  *    support of your modified version, and
  27.  *   4. retain our contact information in regard to use of the base
  28.  *    software.
  29.  * Permission to distribute the released version of the source code along
  30.  * with corresponding source modifications in the form of a patch file is
  31.  * granted with same provisions 2 through 4 for binary distributions.
  32.  *
  33.  * This software is provided "as is" without express or implied warranty
  34.  * to the extent permitted by applicable law.
  35. ]*/
  36.  
  37. #ifdef AMIGA_AC_5
  38. # include <exec/types.h>
  39. #endif /* AMIGA_AC_5 */
  40.  
  41. #include "plot.h"
  42. #include "setshow.h"
  43.  
  44. extern int key_vpos, key_hpos, key_just;
  45. extern int datatype[];
  46. extern char timefmt[];
  47.  
  48. static void save_range __PROTO((FILE * fp, int axis, double min, double max, int autosc, char *text));
  49. static void save_tics __PROTO((FILE * fp, int where, int axis, struct ticdef * tdef, TBOOLEAN rotate, char *text));
  50. static void save_position __PROTO((FILE * fp, struct position * pos));
  51. static void save_functions__sub __PROTO((FILE * fp));
  52. static void save_variables__sub __PROTO((FILE * fp));
  53. static int lf_pop __PROTO((void));
  54. static void lf_push __PROTO((FILE * fp));
  55. static int find_maxl_cntr __PROTO((struct gnuplot_contours * contours, int *count));
  56.  
  57.  
  58. #define SAVE_NUM_OR_TIME(fp, x, axis) \
  59. do{if (datatype[axis]==TIME) { \
  60.   char s[80]; char *p; \
  61.   putc('"', fp);   \
  62.   gstrftime(s,80,timefmt,(double)(x)); \
  63.   for(p=s; *p; ++p) {\
  64.    if ( *p == '\t' ) fputs("\\t",fp);\
  65.    else if (*p == '\n') fputs("\\n",fp); \
  66.    else if ( *p > 126 || *p < 32 ) fprintf(fp,"\\%03o",*p);\
  67.    else putc(*p, fp);\
  68.   }\
  69.   putc('"', fp);\
  70.  } else {\
  71.   fprintf(fp,"%#g",x);\
  72. }} while(0)
  73.  
  74.  
  75. /* State information for load_file(), to recover from errors
  76.  * and properly handle recursive load_file calls
  77.  */
  78. typedef struct lf_state_struct LFS;
  79. struct lf_state_struct {
  80.     FILE *fp;            /* file pointer for load file */
  81.     char *name;            /* name of file */
  82.     TBOOLEAN interactive;    /* value of interactive flag on entry */
  83.     TBOOLEAN do_load_arg_substitution;    /* likewise ... */
  84.     int inline_num;        /* inline_num on entry */
  85.     LFS *prev;            /* defines a stack */
  86.     char *call_args[10];    /* args when file is 'call'ed instead of 'load'ed */
  87. } *lf_head = NULL;        /* NULL if not in load_file */
  88.  
  89. /* these two could be in load_file, except for error recovery */
  90. extern TBOOLEAN do_load_arg_substitution;
  91. extern char *call_args[10];
  92.  
  93. /*
  94.  * cp_alloc() allocates a curve_points structure that can hold 'num'
  95.  * points.
  96.  */
  97. struct curve_points *
  98.  cp_alloc(num)
  99. int num;
  100. {
  101.     struct curve_points *cp;
  102.  
  103.     cp = (struct curve_points *) gp_alloc((unsigned long) sizeof(struct curve_points), "curve");
  104.     cp->p_max = (num >= 0 ? num : 0);
  105.  
  106.     if (num > 0) {
  107.     cp->points = (struct coordinate GPHUGE *)
  108.         gp_alloc((unsigned long) num * sizeof(struct coordinate), "curve points");
  109.     } else
  110.     cp->points = (struct coordinate GPHUGE *) NULL;
  111.     cp->next_cp = NULL;
  112.     cp->title = NULL;
  113.     return (cp);
  114. }
  115.  
  116.  
  117. /*
  118.  * cp_extend() reallocates a curve_points structure to hold "num"
  119.  * points. This will either expand or shrink the storage.
  120.  */
  121. void cp_extend(cp, num)
  122. struct curve_points *cp;
  123. int num;
  124. {
  125.  
  126. #if defined(DOS16) || defined(WIN16)
  127.     /* Make sure we do not allocate more than 64k points in msdos since 
  128.        * indexing is done with 16-bit int
  129.        * Leave some bytes for malloc maintainance.
  130.      */
  131.     if (num > 32700)
  132.     int_error("Array index must be less than 32k in msdos", NO_CARET);
  133. #endif /* MSDOS */
  134.  
  135.     if (num == cp->p_max)
  136.     return;
  137.  
  138.     if (num > 0) {
  139.     if (cp->points == NULL) {
  140.         cp->points = (struct coordinate GPHUGE *)
  141.         gp_alloc((unsigned long) num * sizeof(struct coordinate), "curve points");
  142.     } else {
  143.         cp->points = (struct coordinate GPHUGE *)
  144.         gp_realloc(cp->points, (unsigned long) num * sizeof(struct coordinate), "expanding curve points");
  145.     }
  146.     cp->p_max = num;
  147.     } else {
  148.     if (cp->points != (struct coordinate GPHUGE *) NULL)
  149.         free(cp->points);
  150.     cp->points = (struct coordinate GPHUGE *) NULL;
  151.     cp->p_max = 0;
  152.     }
  153. }
  154.  
  155. /*
  156.  * cp_free() releases any memory which was previously malloc()'d to hold
  157.  *   curve points (and recursively down the linked list).
  158.  */
  159. void cp_free(cp)
  160. struct curve_points *cp;
  161. {
  162.     if (cp) {
  163.     cp_free(cp->next_cp);
  164.     if (cp->title)
  165.         free((char *) cp->title);
  166.     if (cp->points)
  167.         free((char *) cp->points);
  168.     free((char *) cp);
  169.     }
  170. }
  171.  
  172. /*
  173.  * iso_alloc() allocates a iso_curve structure that can hold 'num'
  174.  * points.
  175.  */
  176. struct iso_curve *
  177.  iso_alloc(num)
  178. int num;
  179. {
  180.     struct iso_curve *ip;
  181.     ip = (struct iso_curve *) gp_alloc((unsigned long) sizeof(struct iso_curve), "iso curve");
  182.     ip->p_max = (num >= 0 ? num : 0);
  183.     if (num > 0) {
  184.     ip->points = (struct coordinate GPHUGE *)
  185.         gp_alloc((unsigned long) num * sizeof(struct coordinate), "iso curve points");
  186.     } else
  187.     ip->points = (struct coordinate GPHUGE *) NULL;
  188.     ip->next = NULL;
  189.     return (ip);
  190. }
  191.  
  192. /*
  193.  * iso_extend() reallocates a iso_curve structure to hold "num"
  194.  * points. This will either expand or shrink the storage.
  195.  */
  196. void iso_extend(ip, num)
  197. struct iso_curve *ip;
  198. int num;
  199. {
  200.     if (num == ip->p_max)
  201.     return;
  202.  
  203. #if defined(DOS16) || defined(WIN16)
  204.     /* Make sure we do not allocate more than 64k points in msdos since 
  205.        * indexing is done with 16-bit int
  206.        * Leave some bytes for malloc maintainance.
  207.      */
  208.     if (num > 32700)
  209.     int_error("Array index must be less than 32k in msdos", NO_CARET);
  210. #endif /* 16bit (Win)Doze */
  211.  
  212.     if (num > 0) {
  213.     if (ip->points == NULL) {
  214.         ip->points = (struct coordinate GPHUGE *)
  215.         gp_alloc((unsigned long) num * sizeof(struct coordinate), "iso curve points");
  216.     } else {
  217.         ip->points = (struct coordinate GPHUGE *)
  218.         gp_realloc(ip->points, (unsigned long) num * sizeof(struct coordinate), "expanding curve points");
  219.     }
  220.     ip->p_max = num;
  221.     } else {
  222.     if (ip->points != (struct coordinate GPHUGE *) NULL)
  223.         free(ip->points);
  224.     ip->points = (struct coordinate GPHUGE *) NULL;
  225.     ip->p_max = 0;
  226.     }
  227. }
  228.  
  229. /*
  230.  * iso_free() releases any memory which was previously malloc()'d to hold
  231.  *   iso curve points.
  232.  */
  233. void iso_free(ip)
  234. struct iso_curve *ip;
  235. {
  236.     if (ip) {
  237.     if (ip->points)
  238.         free((char *) ip->points);
  239.     free((char *) ip);
  240.     }
  241. }
  242.  
  243. /*
  244.  * sp_alloc() allocates a surface_points structure that can hold 'num_iso_1'
  245.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  246.  * 'num_samp_1' samples.
  247.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  248.  */
  249. struct surface_points *
  250.  sp_alloc(num_samp_1, num_iso_1, num_samp_2, num_iso_2)
  251. int num_samp_1, num_iso_1, num_samp_2, num_iso_2;
  252. {
  253.     struct surface_points *sp;
  254.  
  255.     sp = (struct surface_points *) gp_alloc((unsigned long) sizeof(struct surface_points), "surface");
  256.     sp->next_sp = NULL;
  257.     sp->title = NULL;
  258.     sp->contours = NULL;
  259.     sp->iso_crvs = NULL;
  260.     sp->num_iso_read = 0;
  261.  
  262.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  263.     int i;
  264.     struct iso_curve *icrv;
  265.  
  266.     for (i = 0; i < num_iso_1; i++) {
  267.         icrv = iso_alloc(num_samp_2);
  268.         icrv->next = sp->iso_crvs;
  269.         sp->iso_crvs = icrv;
  270.     }
  271.     for (i = 0; i < num_iso_2; i++) {
  272.         icrv = iso_alloc(num_samp_1);
  273.         icrv->next = sp->iso_crvs;
  274.         sp->iso_crvs = icrv;
  275.     }
  276.     } else
  277.     sp->iso_crvs = (struct iso_curve *) NULL;
  278.  
  279.     return (sp);
  280. }
  281.  
  282. /*
  283.  * sp_replace() updates a surface_points structure so it can hold 'num_iso_1'
  284.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  285.  * 'num_samp_1' samples.
  286.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  287.  */
  288. void sp_replace(sp, num_samp_1, num_iso_1, num_samp_2, num_iso_2)
  289. struct surface_points *sp;
  290. int num_samp_1, num_iso_1, num_samp_2, num_iso_2;
  291. {
  292.     int i;
  293.     struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  294.  
  295.     while (icrvs) {
  296.     icrv = icrvs;
  297.     icrvs = icrvs->next;
  298.     iso_free(icrv);
  299.     }
  300.     sp->iso_crvs = NULL;
  301.  
  302.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  303.     for (i = 0; i < num_iso_1; i++) {
  304.         icrv = iso_alloc(num_samp_2);
  305.         icrv->next = sp->iso_crvs;
  306.         sp->iso_crvs = icrv;
  307.     }
  308.     for (i = 0; i < num_iso_2; i++) {
  309.         icrv = iso_alloc(num_samp_1);
  310.         icrv->next = sp->iso_crvs;
  311.         sp->iso_crvs = icrv;
  312.     }
  313.     } else
  314.     sp->iso_crvs = (struct iso_curve *) NULL;
  315. }
  316.  
  317. /*
  318.  * sp_free() releases any memory which was previously malloc()'d to hold
  319.  *   surface points.
  320.  */
  321. void sp_free(sp)
  322. struct surface_points *sp;
  323. {
  324.     if (sp) {
  325.     sp_free(sp->next_sp);
  326.     if (sp->title)
  327.         free((char *) sp->title);
  328.     if (sp->contours) {
  329.         struct gnuplot_contours *cntr, *cntrs = sp->contours;
  330.  
  331.         while (cntrs) {
  332.         cntr = cntrs;
  333.         cntrs = cntrs->next;
  334.         free(cntr->coords);
  335.         free(cntr);
  336.         }
  337.     }
  338.     if (sp->iso_crvs) {
  339.         struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  340.  
  341.         while (icrvs) {
  342.         icrv = icrvs;
  343.         icrvs = icrvs->next;
  344.         iso_free(icrv);
  345.         }
  346.     }
  347.     free((char *) sp);
  348.     }
  349. }
  350.  
  351.  
  352. /*
  353.  *  functions corresponding to the arguments of the GNUPLOT `save` command
  354.  */
  355. void save_functions(fp)
  356. FILE *fp;
  357. {
  358.     if (fp) {
  359.     show_version(fp);        /* I _love_ information written */
  360.     save_functions__sub(fp);    /* at the top and the end of an */
  361.     fputs("#    EOF\n", fp);    /* human readable ASCII file.   */
  362.     (void) fclose(fp);    /*                        (JFi) */
  363.     } else
  364.     os_error("Cannot open save file", c_token);
  365. }
  366.  
  367.  
  368. void save_variables(fp)
  369. FILE *fp;
  370. {
  371.     if (fp) {
  372.     show_version(fp);
  373.     save_variables__sub(fp);
  374.     fputs("#    EOF\n", fp);
  375.     (void) fclose(fp);
  376.     } else
  377.     os_error("Cannot open save file", c_token);
  378. }
  379.  
  380.  
  381. void save_set(fp)
  382. FILE *fp;
  383. {
  384.     if (fp) {
  385.     show_version(fp);
  386.     save_set_all(fp);
  387.     fputs("#    EOF\n", fp);
  388.     (void) fclose(fp);
  389.     } else
  390.     os_error("Cannot open save file", c_token);
  391. }
  392.  
  393.  
  394. void save_all(fp)
  395. FILE *fp;
  396. {
  397.     if (fp) {
  398.     show_version(fp);
  399.     save_set_all(fp);
  400.     save_functions__sub(fp);
  401.     save_variables__sub(fp);
  402.     fprintf(fp, "%s\n", replot_line);
  403.         if (wri_to_fil_last_fit_cmd(NULL)) {
  404.            fputs("## ", fp);
  405.            wri_to_fil_last_fit_cmd(fp);
  406.            putc('\n', fp);
  407.         }
  408.     fputs("#    EOF\n", fp);
  409.     (void) fclose(fp);
  410.     } else
  411.     os_error("Cannot open save file", c_token);
  412. }
  413.  
  414. /*
  415.  *  auxiliary functions
  416.  */
  417.  
  418. static void save_functions__sub(fp)
  419. FILE *fp;
  420. {
  421.     register struct udft_entry *udf = first_udf;
  422.  
  423.     while (udf) {
  424.     if (udf->definition) {
  425.         fprintf(fp, "%s\n", udf->definition);
  426.     }
  427.     udf = udf->next_udf;
  428.     }
  429. }
  430.  
  431. static void save_variables__sub(fp)
  432. FILE *fp;
  433. {
  434.     register struct udvt_entry *udv = first_udv->next_udv;    /* always skip pi */
  435.  
  436.     while (udv) {
  437.     if (!udv->udv_undef) {
  438.         fprintf(fp, "%s = ", udv->udv_name);
  439.         disp_value(fp, &(udv->udv_value));
  440.         (void) putc('\n', fp);
  441.     }
  442.     udv = udv->next_udv;
  443.     }
  444. }
  445.  
  446. void save_set_all(fp)
  447. FILE *fp;
  448. {
  449.     struct text_label *this_label;
  450.     struct arrow_def *this_arrow;
  451.     struct linestyle_def *this_linestyle;
  452.     char str[MAX_LINE_LEN+1];
  453.  
  454.     /* opinions are split as to whether we save term and outfile
  455.      * as a compromise, we output them as comments !
  456.      */
  457.     if (term)
  458.     fprintf(fp, "# set terminal %s %s\n", term->name, term_options);
  459.     else
  460.     fputs("# set terminal unknown\n", fp);
  461.  
  462.     if (outstr)
  463.     fprintf(fp, "# set output '%s'\n", outstr);
  464.     else
  465.     fputs("# set output\n", fp);
  466.  
  467.     fprintf(fp, "\
  468. set %sclip points\n\
  469. set %sclip one\n\
  470. set %sclip two\n\
  471. set bar %f\n",
  472.         (clip_points) ? "" : "no",
  473.         (clip_lines1) ? "" : "no",
  474.         (clip_lines2) ? "" : "no",
  475.         bar_size);
  476.  
  477.     if (draw_border)
  478.     /* HBB 980609: handle border linestyle, too */
  479.     fprintf(fp, "set border %d lt %d lw %.3f\n", draw_border, border_lp.l_type + 1, border_lp.l_width);
  480.     else
  481.     fprintf(fp, "set noborder\n");
  482.  
  483.     fprintf(fp, "\
  484. set xdata%s\n\
  485. set ydata%s\n\
  486. set zdata%s\n\
  487. set x2data%s\n\
  488. set y2data%s\n",
  489.         datatype[FIRST_X_AXIS] == TIME ? " time" : "",
  490.         datatype[FIRST_Y_AXIS] == TIME ? " time" : "",
  491.         datatype[FIRST_Z_AXIS] == TIME ? " time" : "",
  492.         datatype[SECOND_X_AXIS] == TIME ? " time" : "",
  493.         datatype[SECOND_Y_AXIS] == TIME ? " time" : "");
  494.  
  495.     if (boxwidth < 0.0)
  496.     fputs("set boxwidth\n", fp);
  497.     else
  498.     fprintf(fp, "set boxwidth %g\n", boxwidth);
  499.     if (dgrid3d)
  500.     fprintf(fp, "set dgrid3d %d,%d, %d\n",
  501.         dgrid3d_row_fineness,
  502.         dgrid3d_col_fineness,
  503.         dgrid3d_norm_value);
  504.  
  505.     fprintf(fp, "set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
  506.     fprintf(fp, "set format x \"%s\"\n", conv_text(str, xformat));
  507.     fprintf(fp, "set format y \"%s\"\n", conv_text(str, yformat));
  508.     fprintf(fp, "set format x2 \"%s\"\n", conv_text(str, x2format));
  509.     fprintf(fp, "set format y2 \"%s\"\n", conv_text(str, y2format));
  510.     fprintf(fp, "set format z \"%s\"\n", conv_text(str, zformat));
  511.     fprintf(fp, "set angles %s\n",
  512.         (angles_format == ANGLES_RADIANS) ? "radians" : "degrees");
  513.  
  514.     if (work_grid.l_type == 0)
  515.     fputs("set nogrid\n", fp);
  516.     else {
  517.     if (polar_grid_angle)    /* set angle already output */
  518.         fprintf(fp, "set grid polar %f\n", polar_grid_angle / ang2rad);
  519.     else
  520.         fputs("set grid nopolar\n", fp);
  521.     fprintf(fp, "set grid %sxtics %sytics %sztics %sx2tics %sy2tics %smxtics %smytics %smztics %smx2tics %smy2tics lt %d lw %.3f, lt %d lw %.3f\n",
  522.         work_grid.l_type & GRID_X ? "" : "no",
  523.         work_grid.l_type & GRID_Y ? "" : "no",
  524.         work_grid.l_type & GRID_Z ? "" : "no",
  525.         work_grid.l_type & GRID_X2 ? "" : "no",
  526.         work_grid.l_type & GRID_Y2 ? "" : "no",
  527.         work_grid.l_type & GRID_MX ? "" : "no",
  528.         work_grid.l_type & GRID_MY ? "" : "no",
  529.         work_grid.l_type & GRID_MZ ? "" : "no",
  530.         work_grid.l_type & GRID_MX2 ? "" : "no",
  531.         work_grid.l_type & GRID_MY2 ? "" : "no",
  532.         grid_lp.l_type + 1, grid_lp.l_width,
  533.         mgrid_lp.l_type + 1, mgrid_lp.l_width);
  534.     }
  535.     fprintf(fp, "set key title \"%s\"\n", conv_text(str, key_title));
  536.     switch (key) {
  537.     case -1:{
  538.         fputs("set key", fp);
  539.         switch (key_hpos) {
  540.         case TRIGHT:
  541.         fputs(" right", fp);
  542.         break;
  543.         case TLEFT:
  544.         fputs(" left", fp);
  545.         break;
  546.         case TOUT:
  547.         fputs(" out", fp);
  548.         break;
  549.         }
  550.         switch (key_vpos) {
  551.         case TTOP:
  552.         fputs(" top", fp);
  553.         break;
  554.         case TBOTTOM:
  555.         fputs(" bottom", fp);
  556.         break;
  557.         case TUNDER:
  558.         fputs(" below", fp);
  559.         break;
  560.         }
  561.         break;
  562.     }
  563.     case 0:
  564.     fputs("set nokey\n", fp);
  565.     break;
  566.     case 1:
  567.     fputs("set key ", fp);
  568.     save_position(fp, &key_user_pos);
  569.     break;
  570.     }
  571.     if (key) {
  572.     fprintf(fp, " %s %sreverse box linetype %d linewidth %.3f samplen %g spacing %g width %g\n",
  573.         key_just == JLEFT ? "Left" : "Right",
  574.         key_reverse ? "" : "no",
  575.         key_box.l_type + 1, key_box.l_width, key_swidth, key_vert_factor, key_width_fix);
  576.     }
  577.     fputs("set nolabel\n", fp);
  578.     for (this_label = first_label; this_label != NULL;
  579.      this_label = this_label->next) {
  580.     fprintf(fp, "set label %d \"%s\" at ",
  581.         this_label->tag,
  582.         conv_text(str, this_label->text));
  583.     save_position(fp, &this_label->place);
  584.  
  585.     switch (this_label->pos) {
  586.     case LEFT:
  587.         fputs(" left", fp);
  588.         break;
  589.     case CENTRE:
  590.         fputs(" centre", fp);
  591.         break;
  592.     case RIGHT:
  593.         fputs(" right", fp);
  594.         break;
  595.     }
  596.     fprintf(fp, " %srotate", this_label->rotate ? "" : "no");
  597.     if ((this_label->font)[0] != NUL)
  598.         fprintf(fp, " font \"%s\"", this_label->font);
  599.     /* Entry font added by DJL */
  600.     fputc('\n', fp);
  601.     }
  602.     fputs("set noarrow\n", fp);
  603.     for (this_arrow = first_arrow; this_arrow != NULL;
  604.      this_arrow = this_arrow->next) {
  605.     fprintf(fp, "set arrow %d from ", this_arrow->tag);
  606.     save_position(fp, &this_arrow->start);
  607.     fputs(" to ", fp);
  608.     save_position(fp, &this_arrow->end);
  609.     fprintf(fp, " %s linetype %d linewidth %.3f\n",
  610.         this_arrow->head ? "" : " nohead",
  611.         this_arrow->lp_properties.l_type + 1,
  612.         this_arrow->lp_properties.l_width);
  613.     }
  614.     fputs("set nolinestyle\n", fp);
  615.     for (this_linestyle = first_linestyle; this_linestyle != NULL;
  616.      this_linestyle = this_linestyle->next) {
  617.     fprintf(fp, "set linestyle %d ", this_linestyle->tag);
  618.     fprintf(fp, "linetype %d linewidth %.3f pointtype %d pointsize %.3f\n",
  619.         this_linestyle->lp_properties.l_type + 1,
  620.         this_linestyle->lp_properties.l_width,
  621.         this_linestyle->lp_properties.p_type + 1,
  622.         this_linestyle->lp_properties.p_size);
  623.     }
  624.     fputs("set nologscale\n", fp);
  625.     if (is_log_x)
  626.     fprintf(fp, "set logscale x %g\n", base_log_x);
  627.     if (is_log_y)
  628.     fprintf(fp, "set logscale y %g\n", base_log_y);
  629.     if (is_log_z)
  630.     fprintf(fp, "set logscale z %g\n", base_log_z);
  631.     if (is_log_x2)
  632.     fprintf(fp, "set logscale x2 %g\n", base_log_x2);
  633.     if (is_log_y2)
  634.     fprintf(fp, "set logscale y2 %g\n", base_log_y2);
  635.  
  636.     fprintf(fp, "\
  637. set offsets %g, %g, %g, %g\n\
  638. set pointsize %g\n\
  639. set encoding %s\n\
  640. set %spolar\n\
  641. set %sparametric\n\
  642. set view %g, %g, %g, %g\n\
  643. set samples %d, %d\n\
  644. set isosamples %d, %d\n\
  645. set %ssurface\n\
  646. set %scontour",
  647.         loff, roff, toff, boff,
  648.         pointsize,
  649.         encoding_names[encoding],
  650.         (polar) ? "" : "no",
  651.         (parametric) ? "" : "no",
  652.         surface_rot_x, surface_rot_z, surface_scale, surface_zscale,
  653.         samples_1, samples_2,
  654.         iso_samples_1, iso_samples_2,
  655.         (draw_surface) ? "" : "no",
  656.         (draw_contour) ? "" : "no");
  657.  
  658.     switch (draw_contour) {
  659.     case CONTOUR_NONE:
  660.     fputc('\n', fp);
  661.     break;
  662.     case CONTOUR_BASE:
  663.     fputs(" base\n", fp);
  664.     break;
  665.     case CONTOUR_SRF:
  666.     fputs(" surface\n", fp);
  667.     break;
  668.     case CONTOUR_BOTH:
  669.     fputs(" both\n", fp);
  670.     break;
  671.     }
  672.     if (label_contours)
  673.     fprintf(fp, "set clabel '%s'\n", contour_format);
  674.     else
  675.     fputs("set noclabel\n", fp);
  676.  
  677.     fputs("set mapping ", fp);
  678.     switch(mapping3d) {
  679.     case MAP3D_SPHERICAL:
  680.     fputs("spherical\n", fp);
  681.     break;
  682.     case MAP3D_CYLINDRICAL:
  683.     fputs("cylindrical\n", fp);
  684.     break;
  685.     case MAP3D_CARTESIAN:
  686.     default:
  687.     fputs("cartesian\n", fp);
  688.     break;
  689.     }
  690.  
  691.     if (missing_val != NULL)
  692.     fprintf(fp, "set missing %s\n", missing_val);
  693.  
  694.     save_hidden3doptions(fp);
  695.     fprintf(fp, "set cntrparam order %d\n", contour_order);
  696.     fputs("set cntrparam ", fp);
  697.     switch (contour_kind) {
  698.     case CONTOUR_KIND_LINEAR:
  699.     fputs("linear\n", fp);
  700.     break;
  701.     case CONTOUR_KIND_CUBIC_SPL:
  702.     fputs("cubicspline\n", fp);
  703.     break;
  704.     case CONTOUR_KIND_BSPLINE:
  705.     fputs("bspline\n", fp);
  706.     break;
  707.     }
  708.     fputs("set cntrparam levels ", fp);
  709.     switch (levels_kind) {
  710.     case LEVELS_AUTO:
  711.     fprintf(fp, "auto %d\n", contour_levels);
  712.     break;
  713.     case LEVELS_INCREMENTAL:
  714.     fprintf(fp, "incremental %g,%g,%g\n",
  715.         levels_list[0], levels_list[1],
  716.         levels_list[0] + levels_list[1] * contour_levels);
  717.     break;
  718.     case LEVELS_DISCRETE:
  719.     {
  720.         int i;
  721.         fprintf(fp, "discrete %g", levels_list[0]);
  722.         for (i = 1; i < contour_levels; i++)
  723.         fprintf(fp, ",%g ", levels_list[i]);
  724.         fputc('\n', fp);
  725.     }
  726.     }
  727.     fprintf(fp, "\
  728. set cntrparam points %d\n\
  729. set size ratio %g %g,%g\n\
  730. set origin %g,%g\n\
  731. set data style ",
  732.         contour_pts,
  733.         aspect_ratio, xsize, ysize,
  734.         xoffset, yoffset);
  735.  
  736.     switch (data_style) {
  737.     case LINES:
  738.     fputs("lines\n", fp);
  739.     break;
  740.     case POINTSTYLE:
  741.     fputs("points\n", fp);
  742.     break;
  743.     case IMPULSES:
  744.     fputs("impulses\n", fp);
  745.     break;
  746.     case LINESPOINTS:
  747.     fputs("linespoints\n", fp);
  748.     break;
  749.     case DOTS:
  750.     fputs("dots\n", fp);
  751.     break;
  752.     case YERRORBARS:
  753.     fputs("yerrorbars\n", fp);
  754.     break;
  755.     case XERRORBARS:
  756.     fputs("xerrorbars\n", fp);
  757.     break;
  758.     case XYERRORBARS:
  759.     fputs("xyerrorbars\n", fp);
  760.     break;
  761.     case BOXES:
  762.     fputs("boxes\n", fp);
  763.     break;
  764.     case BOXERROR:
  765.     fputs("boxerrorbars\n", fp);
  766.     break;
  767.     case BOXXYERROR:
  768.     fputs("boxxyerrorbars\n", fp);
  769.     break;
  770.     case STEPS:
  771.     fputs("steps\n", fp);
  772.     break;            /* JG */
  773.     case FSTEPS:
  774.     fputs("fsteps\n", fp);
  775.     break;            /* HOE */
  776.     case HISTEPS:
  777.     fputs("histeps\n", fp);
  778.     break;            /* CAC */
  779.     case VECTOR:
  780.     fputs("vector\n", fp);
  781.     break;
  782.     case FINANCEBARS:
  783.     fputs("financebars\n", fp);
  784.     break;
  785.     case CANDLESTICKS:
  786.     fputs("candlesticks\n", fp);
  787.     break;
  788.     }
  789.     fputs("set function style ", fp);
  790.     switch (func_style) {
  791.     case LINES:
  792.     fputs("lines\n", fp);
  793.     break;
  794.     case POINTSTYLE:
  795.     fputs("points\n", fp);
  796.     break;
  797.     case IMPULSES:
  798.     fputs("impulses\n", fp);
  799.     break;
  800.     case LINESPOINTS:
  801.     fputs("linespoints\n", fp);
  802.     break;
  803.     case DOTS:
  804.     fputs("dots\n", fp);
  805.     break;
  806.     case YERRORBARS:
  807.     fputs("yerrorbars\n", fp);
  808.     break;
  809.     case XERRORBARS:
  810.     fputs("xerrorbars\n", fp);
  811.     break;
  812.     case XYERRORBARS:
  813.     fputs("xyerrorbars\n", fp);
  814.     break;
  815.     case BOXXYERROR:
  816.     fputs("boxxyerrorbars\n", fp);
  817.     break;
  818.     case BOXES:
  819.     fputs("boxes\n", fp);
  820.     break;
  821.     case BOXERROR:
  822.     fputs("boxerrorbars\n", fp);
  823.     break;
  824.     case STEPS:
  825.     fputs("steps\n", fp);
  826.     break;            /* JG */
  827.     case FSTEPS:
  828.     fputs("fsteps\n", fp);
  829.     break;            /* HOE */
  830.     case HISTEPS:
  831.     fputs("histeps\n", fp);
  832.     break;            /* CAC */
  833.     case VECTOR:
  834.     fputs("vector\n", fp);
  835.     break;
  836.     case FINANCEBARS:
  837.     fputs("financebars\n", fp);
  838.     break;
  839.     case CANDLESTICKS:
  840.     fputs("candlesticks\n", fp);
  841.     break;
  842.     default:
  843.         /* HBB: default case demanded by gcc, still needed ?? */
  844.     fputs("---error!---\n", fp);
  845.     }
  846.  
  847.     fprintf(fp, "\
  848. set xzeroaxis lt %d lw %.3f\n\
  849. set x2zeroaxis lt %d lw %.3f\n\
  850. set yzeroaxis lt %d lw %.3f\n\
  851. set y2zeroaxis lt %d lw %.3f\n\
  852. set tics %s\n\
  853. set ticslevel %g\n\
  854. set ticscale %g %g\n",
  855.         xzeroaxis.l_type + 1, xzeroaxis.l_width,
  856.         x2zeroaxis.l_type + 1, x2zeroaxis.l_width,
  857.         yzeroaxis.l_type + 1, yzeroaxis.l_width,
  858.         y2zeroaxis.l_type + 1, y2zeroaxis.l_width,
  859.         (tic_in) ? "in" : "out",
  860.         ticslevel,
  861.         ticscale, miniticscale);
  862.  
  863. #define SAVE_XYZLABEL(name,lab) { \
  864.   fprintf(fp, "set %s \"%s\" %f,%f ", \
  865.     name, conv_text(str,lab.text),lab.xoffset,lab.yoffset); \
  866.   fprintf(fp, " \"%s\"\n", conv_text(str, lab.font)); \
  867. }
  868.  
  869.  
  870. #define SAVE_MINI(name,m,freq) switch(m&TICS_MASK) { \
  871.  case 0: fprintf(fp, "set no%s\n", name); break; \
  872.  case MINI_AUTO: fprintf(fp, "set %s\n",name); break; \
  873.  case MINI_DEFAULT: fprintf(fp, "set %s default\n",name); break; \
  874.  case MINI_USER: fprintf(fp, "set %s %f\n", name, freq); break; \
  875. }
  876.     SAVE_MINI("mxtics", mxtics, mxtfreq)
  877.     SAVE_MINI("mytics", mytics, mytfreq)
  878.     SAVE_MINI("mx2tics", mx2tics, mx2tfreq)
  879.     SAVE_MINI("my2tics", my2tics, my2tfreq)
  880.     save_tics(fp, xtics, FIRST_X_AXIS, &xticdef, rotate_xtics, "x");
  881.     save_tics(fp, ytics, FIRST_Y_AXIS, &yticdef, rotate_ytics, "y");
  882.     save_tics(fp, ztics, FIRST_Z_AXIS, &zticdef, rotate_ztics, "z");
  883.     save_tics(fp, x2tics, SECOND_X_AXIS, &x2ticdef, rotate_x2tics, "x2");
  884.     save_tics(fp, y2tics, SECOND_Y_AXIS, &y2ticdef, rotate_y2tics, "y2");
  885.     SAVE_XYZLABEL("title", title);
  886.  
  887.     fprintf(fp, "set %s \"%s\" %s %srotate %f,%f ",
  888.         "timestamp", conv_text(str, timelabel.text),
  889.         (timelabel_bottom ? "bottom" : "top"),
  890.         (timelabel_rotate ? "" : "no"),
  891.         timelabel.xoffset, timelabel.yoffset);
  892.     fprintf(fp, " \"%s\"\n", conv_text(str, timelabel.font));
  893.  
  894.     save_range(fp, R_AXIS, rmin, rmax, autoscale_r, "r");
  895.     save_range(fp, T_AXIS, tmin, tmax, autoscale_t, "t");
  896.     save_range(fp, U_AXIS, umin, umax, autoscale_u, "u");
  897.     save_range(fp, V_AXIS, vmin, vmax, autoscale_v, "v");
  898.  
  899.     SAVE_XYZLABEL("xlabel", xlabel);
  900.     SAVE_XYZLABEL("x2label", x2label);
  901.  
  902.     if (strlen(timefmt)) {
  903.     fprintf(fp, "set timefmt \"%s\"\n", conv_text(str, timefmt));
  904.     }
  905.     save_range(fp, FIRST_X_AXIS, xmin, xmax, autoscale_x, "x");
  906.     save_range(fp, SECOND_X_AXIS, x2min, x2max, autoscale_x2, "x2");
  907.  
  908.     SAVE_XYZLABEL("ylabel", ylabel);
  909.     SAVE_XYZLABEL("y2label", y2label);
  910.  
  911.     save_range(fp, FIRST_Y_AXIS, ymin, ymax, autoscale_y, "y");
  912.     save_range(fp, SECOND_Y_AXIS, y2min, y2max, autoscale_y2, "y2");
  913.  
  914.     SAVE_XYZLABEL("zlabel", zlabel);
  915.     save_range(fp, FIRST_Z_AXIS, zmin, zmax, autoscale_z, "z");
  916.  
  917.     fprintf(fp, "set zero %g\n", zero);
  918.     fprintf(fp, "set lmargin %d\nset bmargin %d\nset rmargin %d\nset tmargin %d\n",
  919.         lmargin, bmargin, rmargin, tmargin);
  920.  
  921.     fprintf(fp, "set locale \"%s\"\n", cur_locale);
  922. }
  923.  
  924. static void save_tics(fp, where, axis, tdef, rotate, text)
  925. FILE *fp;
  926. int where;
  927. int axis;
  928. struct ticdef *tdef;
  929. TBOOLEAN rotate;
  930. char *text;
  931. {
  932.     char str[MAX_LINE_LEN + 1];
  933.  
  934.     if (where == NO_TICS) {
  935.     fprintf(fp, "set no%stics\n", text);
  936.     return;
  937.     }
  938.     fprintf(fp, "set %stics %s %smirror %srotate ", text,
  939.         (where & TICS_MASK) == TICS_ON_AXIS ? "axis" : "border",
  940.         (where & TICS_MIRROR) ? "" : "no", rotate ? "" : "no");
  941.     switch (tdef->type) {
  942.     case TIC_COMPUTED:{
  943.         fputs("autofreq ", fp);
  944.         break;
  945.     }
  946.     case TIC_MONTH:{
  947.         fprintf(fp, "\nset %smtics", text);
  948.         break;
  949.     }
  950.     case TIC_DAY:{
  951.         fprintf(fp, "\nset %cdtics", axis);
  952.         break;
  953.     }
  954.     case TIC_SERIES:
  955.     if (datatype[axis] == TIME) {
  956.         if (tdef->def.series.start != -VERYLARGE) {
  957.         char fd[26];
  958.         gstrftime(fd, 24, timefmt, (double) tdef->def.series.start);
  959.         fprintf(fp, "\"%s\",", conv_text(str, fd));
  960.         }
  961.         fprintf(fp, "%g", tdef->def.series.incr);
  962.  
  963.         if (tdef->def.series.end != VERYLARGE) {
  964.         char td[26];
  965.         gstrftime(td, 24, timefmt, (double) tdef->def.series.end);
  966.         fprintf(fp, ",\"%s\"", conv_text(str, td));
  967.         }
  968.     } else {        /* !TIME */
  969.  
  970.         if (tdef->def.series.start != -VERYLARGE)
  971.         fprintf(fp, "%g,", tdef->def.series.start);
  972.         fprintf(fp, "%g", tdef->def.series.incr);
  973.         if (tdef->def.series.end != VERYLARGE)
  974.         fprintf(fp, ",%g", tdef->def.series.end);
  975.     }
  976.  
  977.     break;
  978.  
  979.     case TIC_USER:{
  980.         register struct ticmark *t;
  981.         int flag_time;
  982.         flag_time = (datatype[axis] == TIME);
  983.         fputs(" (", fp);
  984.         for (t = tdef->def.user; t != NULL; t = t->next) {
  985.         if (t->label)
  986.             fprintf(fp, "\"%s\" ", conv_text(str, t->label));
  987.         if (flag_time) {
  988.             char td[26];
  989.             gstrftime(td, 24, timefmt, (double) t->position);
  990.             fprintf(fp, "\"%s\"", conv_text(str, td));
  991.         } else {
  992.             fprintf(fp, "%g", t->position);
  993.         }
  994.         if (t->next) {
  995.             fputs(", ", fp);
  996.         }
  997.         }
  998.         fputs(")", fp);
  999.         break;
  1000.     }
  1001.     }
  1002.     putc('\n', fp);
  1003. }
  1004.  
  1005. static void save_position(fp, pos)
  1006. FILE *fp;
  1007. struct position *pos;
  1008. {
  1009.     static char *msg[] =
  1010.     {"first_axes ", "second axes ", "graph ", "screen "};
  1011.  
  1012.     assert(first_axes == 0 && second_axes == 1 && graph == 2 && screen == 3);
  1013.  
  1014.     fprintf(fp, "%s%g, %s%g, %s%g",
  1015.         pos->scalex == first_axes ? "" : msg[pos->scalex], pos->x,
  1016.         pos->scaley == pos->scalex ? "" : msg[pos->scaley], pos->y,
  1017.         pos->scalez == pos->scaley ? "" : msg[pos->scalez], pos->z);
  1018. }
  1019.  
  1020. void load_file(fp, name, can_do_args)
  1021. FILE *fp;
  1022. char *name;
  1023. TBOOLEAN can_do_args;
  1024. {
  1025.     register int len;
  1026.  
  1027.     int start, left;
  1028.     int more;
  1029.     int stop = FALSE;
  1030.  
  1031.     lf_push(fp);        /* save state for errors and recursion */
  1032.     do_load_arg_substitution = can_do_args;
  1033.  
  1034.     if (fp == (FILE *) NULL) {
  1035.     /* HBB 980311: alloc() it, to save valuable stack space: */
  1036.     char *errbuf = gp_alloc(BUFSIZ, "load_file errorstring");
  1037.     (void) sprintf(errbuf, "Cannot open %s file '%s'",
  1038.                can_do_args ? "call" : "load", name);
  1039.     os_error(errbuf, c_token);
  1040.     free(errbuf);
  1041.     } else if (fp == stdin) {
  1042.     /* DBT 10-6-98  go interactive if "-" named as load file */
  1043.     interactive = TRUE; 
  1044.     while(!com_line())
  1045.         ;
  1046.     } else {
  1047.     /* go into non-interactive mode during load */
  1048.     /* will be undone below, or in load_file_error */
  1049.     interactive = FALSE;
  1050.     inline_num = 0;
  1051.     infile_name = name;
  1052.  
  1053.     if (can_do_args) {
  1054.         int aix = 0;
  1055.         while (++c_token < num_tokens && aix <= 9) {
  1056.         if (isstring(c_token))
  1057.             m_quote_capture(&call_args[aix++], c_token, c_token);
  1058.         else
  1059.             m_capture(&call_args[aix++], c_token, c_token);
  1060.         }
  1061.  
  1062. /*         A GNUPLOT "call" command can have up to _10_ arguments named "$0"
  1063.    to "$9".  After reading the 10th argument (i.e.: "$9") the variable
  1064.    'aix' contains the value '10' because of the 'aix++' construction
  1065.    in '&call_args[aix++]'.  So I think the following test of 'aix' 
  1066.    should be done against '10' instead of '9'.                (JFi) */
  1067.  
  1068. /*              if (c_token >= num_tokens && aix > 9) */
  1069.         if (c_token >= num_tokens && aix > 10)
  1070.         int_error("too many arguments for CALL <file>", ++c_token);
  1071.     }
  1072.     while (!stop) {        /* read all commands in file */
  1073.         /* read one command */
  1074.         left = input_line_len;
  1075.         start = 0;
  1076.         more = TRUE;
  1077.  
  1078.         while (more) {
  1079.         if (fgets(&(input_line[start]), left, fp) == (char *) NULL) {
  1080.             stop = TRUE;    /* EOF in file */
  1081.             input_line[start] = '\0';
  1082.             more = FALSE;
  1083.         } else {
  1084.             inline_num++;
  1085.             len = strlen(input_line) - 1;
  1086.             if (input_line[len] == '\n') {    /* remove any newline */
  1087.             input_line[len] = '\0';
  1088.             /* Look, len was 1-1 = 0 before, take care here! */
  1089.             if (len > 0)
  1090.                 --len;
  1091.             if (input_line[len] == '\r') {    /* remove any carriage return */
  1092.                 input_line[len] = NUL;
  1093.                 if (len > 0)
  1094.                 --len;
  1095.             }
  1096.             }
  1097.              else if (len + 2 >= left) {
  1098.             extend_input_line();
  1099.             left = input_line_len - len - 1;
  1100.             start = len + 1;
  1101.             continue;    /* don't check for '\' */
  1102.             }
  1103.             if (input_line[len] == '\\') {
  1104.             /* line continuation */
  1105.             start = len;
  1106.             left = input_line_len - start;
  1107.             } else
  1108.             more = FALSE;
  1109.         }
  1110.         }
  1111.  
  1112.         if (strlen(input_line) > 0) {
  1113.         if (can_do_args) {
  1114.             register int il = 0;
  1115.             register char *rl;
  1116.             char *raw_line = rl = gp_alloc((unsigned long) strlen(input_line) + 1, "string");
  1117.  
  1118.             strcpy(raw_line, input_line);
  1119.             *input_line = '\0';
  1120.             while (*rl) {
  1121.             register int aix;
  1122.             if (*rl == '$'
  1123.                 && ((aix = *(++rl)) != 0)    /* HBB 980308: quiet BCC warning */
  1124.                 &&aix >= '0' && aix <= '9') {
  1125.                 if (call_args[aix -= '0']) {
  1126.                 len = strlen(call_args[aix]);
  1127.                 while (input_line_len - il < len + 1) {
  1128.                     extend_input_line();
  1129.                 }
  1130.                 strcpy(input_line + il, call_args[aix]);
  1131.                 il += len;
  1132.                 }
  1133.             } else {
  1134.                 /* substitute for $<n> here */
  1135.                 if (il + 1 > input_line_len) {
  1136.                 extend_input_line();
  1137.                 }
  1138.                 input_line[il++] = *rl;
  1139.             }
  1140.             rl++;
  1141.             }
  1142.             if (il + 1 > input_line_len) {
  1143.             extend_input_line();
  1144.             }
  1145.             input_line[il] = '\0';
  1146.             free(raw_line);
  1147.         }
  1148.         screen_ok = FALSE;    /* make sure command line is
  1149.                        echoed on error */
  1150.         if (do_line())
  1151.             stop = TRUE;
  1152.         }
  1153.     }
  1154.     }
  1155.  
  1156.     /* pop state */
  1157.     (void) lf_pop();        /* also closes file fp */
  1158. }
  1159.  
  1160. /* pop from load_file state stack */
  1161. static TBOOLEAN            /* FALSE if stack was empty */
  1162.  lf_pop()
  1163. {                /* called by load_file and load_file_error */
  1164.     LFS *lf;
  1165.  
  1166.     if (lf_head == NULL)
  1167.     return (FALSE);
  1168.     else {
  1169.     int argindex;
  1170.     lf = lf_head;
  1171.     if (lf->fp != (FILE *)NULL && lf->fp != stdin) {
  1172.         /* DBT 10-6-98  do not close stdin in the case
  1173.          * that "-" is named as a load file
  1174.          */
  1175.         (void) fclose(lf->fp);
  1176.     }
  1177.     for (argindex = 0; argindex < 10; argindex++) {
  1178.         if (call_args[argindex]) {
  1179.         free(call_args[argindex]);
  1180.         }
  1181.         call_args[argindex] = lf->call_args[argindex];
  1182.     }
  1183.     do_load_arg_substitution = lf->do_load_arg_substitution;
  1184.     interactive = lf->interactive;
  1185.     inline_num = lf->inline_num;
  1186.     infile_name = lf->name;
  1187.     lf_head = lf->prev;
  1188.     free((char *) lf);
  1189.     return (TRUE);
  1190.     }
  1191. }
  1192.  
  1193. /* push onto load_file state stack */
  1194. /* essentially, we save information needed to undo the load_file changes */
  1195. static void lf_push(fp)        /* called by load_file */
  1196. FILE *fp;
  1197. {
  1198.     LFS *lf;
  1199.     int argindex;
  1200.  
  1201.     lf = (LFS *) gp_alloc((unsigned long) sizeof(LFS), (char *) NULL);
  1202.     if (lf == (LFS *) NULL) {
  1203.     if (fp != (FILE *) NULL)
  1204.         (void) fclose(fp);    /* it won't be otherwise */
  1205.     int_error("not enough memory to load file", c_token);
  1206.     }
  1207.     lf->fp = fp;        /* save this file pointer */
  1208.     lf->name = infile_name;    /* save current name */
  1209.     lf->interactive = interactive;    /* save current state */
  1210.     lf->inline_num = inline_num;    /* save current line number */
  1211.     lf->do_load_arg_substitution = do_load_arg_substitution;
  1212.     for (argindex = 0; argindex < 10; argindex++) {
  1213.     lf->call_args[argindex] = call_args[argindex];
  1214.     call_args[argindex] = NULL;    /* initially no args */
  1215.     }
  1216.     lf->prev = lf_head;        /* link t}Z~?{ý{þ{ÿ|||f_head = lf;
  1217. }
  1218.  
  1219. /* used for reread  vsnyder@math.jpl.nasa.gov */
  1220. FILE *lf_top()
  1221. {
  1222.     if (lf_head == (LFS *) NULL)
  1223.     return ((FILE *) NULL);
  1224.     return (lf_head->fp);
  1225. }
  1226.  
  1227. /* called from main */
  1228. void load_file_error()
  1229. {
  1230.     /* clean up from error in load_file */
  1231.     /* pop off everything on stack */
  1232.     while (lf_pop());
  1233. }
  1234.  
  1235. /* find char c in string str; return p such that str[p]==c;
  1236.  * if c not in str then p=strlen(str)
  1237.  */
  1238. int instring(str, c)
  1239. char *str;
  1240. int c;
  1241. {
  1242.     int pos = 0;
  1243.  
  1244.     while (str != NULL && *str != NUL && c != *str) {
  1245.     str++;
  1246.     pos++;
  1247.     }
  1248.     return (pos);
  1249. }
  1250.  
  1251. void show_functions()
  1252. {
  1253.     register struct udft_entry *udf = first_udf;
  1254.  
  1255.     fputs("\n\tUser-Defined Functions:\n", stderr);
  1256.  
  1257.     while (udf) {
  1258.     if (udf->definition)
  1259.         fprintf(stderr, "\t%s\n", udf->definition);
  1260.     else
  1261.         fprintf(stderr, "\t%s is undefined\n", udf->udf_name);
  1262.     udf = udf->next_udf;
  1263.     }
  1264. }
  1265.  
  1266.  
  1267. void show_at()
  1268. {
  1269.     (void) putc('\n', stderr);
  1270.     disp_at(temp_at(), 0);
  1271. }
  1272.  
  1273.  
  1274. void disp_at(curr_at, level)
  1275. struct at_type *curr_at;
  1276. int level;
  1277. {
  1278.     register int i, j;
  1279.     register union argument *arg;
  1280.  
  1281.     for (i = 0; i < curr_at->a_count; i++) {
  1282.     (void) putc('\t', stderr);
  1283.     for (j = 0; j < level; j++)
  1284.         (void) putc(' ', stderr);    /* indent */
  1285.  
  1286.     /* print name of instruction */
  1287.  
  1288.     fputs(ft[(int) (curr_at->actions[i].index)].f_name, stderr);
  1289.     arg = &(curr_at->actions[i].arg);
  1290.  
  1291.     /* now print optional argument */
  1292.  
  1293.     switch (curr_at->actions[i].index) {
  1294.     case PUSH:
  1295.         fprintf(stderr, " %s\n", arg->udv_arg->udv_name);
  1296.         break;
  1297.     case PUSHC:
  1298.         (void) putc(' ', stderr);
  1299.         disp_value(stderr, &(arg->v_arg));
  1300.         (void) putc('\n', stderr);
  1301.         break;
  1302.     case PUSHD1:
  1303.         fprintf(stderr, " %c dummy\n",
  1304.             arg->udf_arg->udf_name[0]);
  1305.         break;
  1306.     case PUSHD2:
  1307.         fprintf(stderr, " %c dummy\n",
  1308.             arg->udf_arg->udf_name[1]);
  1309.         break;
  1310.     case CALL:
  1311.         fprintf(stderr, " %s", arg->udf_arg->udf_name);
  1312.         if (level < 6) {
  1313.         if (arg->udf_arg->at) {
  1314.             (void) putc('\n', stderr);
  1315.             disp_at(arg->udf_arg->at, level + 2);    /* recurse! */
  1316.         } else
  1317.             fputs(" (undefined)\n", stderr);
  1318.         } else
  1319.         (void) putc('\n', stderr);
  1320.         break;
  1321.     case CALLN:
  1322.         fprintf(stderr, " %s", arg->udf_arg->udf_name);
  1323.         if (level < 6) {
  1324.         if (arg->udf_arg->at) {
  1325.             (void) putc('\n', stderr);
  1326.             disp_at(arg->udf_arg->at, level + 2);    /* recurse! */
  1327.         } else
  1328.             fputs(" (undefined)\n", stderr);
  1329.         } else
  1330.         (void) putc('\n', stderr);
  1331.         break;
  1332.     case JUMP:
  1333.     case JUMPZ:
  1334.     case JUMPNZ:
  1335.     case JTERN:
  1336.         fprintf(stderr, " +%d\n", arg->j_arg);
  1337.         break;
  1338.     case DOLLARS:
  1339.         fprintf(stderr, " %d\n", arg->v_arg.v.int_val);
  1340.         break;
  1341.     default:
  1342.         (void) putc('\n', stderr);
  1343.     }
  1344.     }
  1345. }
  1346.  
  1347. /* find max len of keys and count keys with len > 0 */
  1348.  
  1349. int find_maxl_keys(plots, count, kcnt)
  1350. struct curve_points *plots;
  1351. int count, *kcnt;
  1352. {
  1353.     int mlen, len, curve, cnt;
  1354.     register struct curve_points *this_plot;
  1355.  
  1356.     mlen = cnt = 0;
  1357.     this_plot = plots;
  1358.     for (curve = 0; curve < count; this_plot = this_plot->next_cp, curve++)
  1359.     if (this_plot->title
  1360.         && ((len = /*assign */ strlen(this_plot->title)) != 0)    /* HBB 980308: quiet BCC warning */
  1361.         ) {
  1362.         cnt++;
  1363.         if (len > mlen)
  1364.         mlen = strlen(this_plot->title);
  1365.     }
  1366.     if (kcnt != NULL)
  1367.     *kcnt = cnt;
  1368.     return (mlen);
  1369. }
  1370.  
  1371.  
  1372. /* calculate the number and max-width of the keys for an splot.
  1373.  * Note that a blank line is issued after each set of contours
  1374.  */
  1375. int find_maxl_keys3d(plots, count, kcnt)
  1376. struct surface_points *plots;
  1377. int count, *kcnt;
  1378. {
  1379.     int mlen, len, surf, cnt;
  1380.     struct surface_points *this_plot;
  1381.  
  1382.     mlen = cnt = 0;
  1383.     this_plot = plots;
  1384.     for (surf = 0; surf < count; this_plot = this_plot->next_sp, surf++) {
  1385.  
  1386.     /* we draw a main entry if there is one, and we are
  1387.      * drawing either surface, or unlabelled contours
  1388.      */
  1389.     if (this_plot->title && *this_plot->title &&
  1390.         (draw_surface || (draw_contour && !label_contours))) {
  1391.         ++cnt;
  1392.         len = strlen(this_plot->title);
  1393.         if (len > mlen)
  1394.         mlen = len;
  1395.     }
  1396.     if (draw_contour && label_contours && this_plot->contours != NULL) {
  1397.         len = find_maxl_cntr(this_plot->contours, &cnt);
  1398.         if (len > mlen)
  1399.         mlen = len;
  1400.     }
  1401.     }
  1402.  
  1403.     if (kcnt != NULL)
  1404.     *kcnt = cnt;
  1405.     return (mlen);
  1406. }
  1407.  
  1408. static int find_maxl_cntr(contours, count)
  1409. struct gnuplot_contours *contours;
  1410. int *count;
  1411. {
  1412.     register int cnt;
  1413.     register int mlen, len;
  1414.     register struct gnuplot_contours *cntrs = contours;
  1415.  
  1416.     mlen = cnt = 0;
  1417.     while (cntrs) {
  1418.     if (label_contours && cntrs->isNewLevel) {
  1419.         len = strlen(cntrs->label);
  1420.         if (len)
  1421.         cnt++;
  1422.         if (len > mlen)
  1423.         mlen = len;
  1424.     }
  1425.     cntrs = cntrs->next;
  1426.     }
  1427.     *count += cnt;
  1428.     return (mlen);
  1429. }
  1430.  
  1431. static void save_range(fp, axis, min, max, autosc, text)
  1432. FILE *fp;
  1433. int axis;
  1434. double min, max;
  1435. TBOOLEAN autosc;
  1436. char *text;
  1437. {
  1438.     int i;
  1439.  
  1440.     i = axis;
  1441.     fprintf(fp, "set %srange [ ", text);
  1442.     if (autosc & 1) {
  1443.     putc('*', fp);
  1444.     } else {
  1445.     SAVE_NUM_OR_TIME(fp, min, axis);
  1446.     }
  1447.     fputs(" : ", fp);
  1448.     if (autosc & 2) {
  1449.     putc('*', fp);
  1450.     } else {
  1451.     SAVE_NUM_OR_TIME(fp, max, axis);
  1452.     }
  1453.  
  1454.     fprintf(fp, " ] %sreverse %swriteback",
  1455.         range_flags[axis] & RANGE_REVERSE ? "" : "no",
  1456.         range_flags[axis] & RANGE_WRITEBACK ? "" : "no");
  1457.  
  1458.     if (autosc) {
  1459.     /* add current (hidden) range as comments */
  1460.     fputs("  # (currently [", fp);
  1461.     if (autosc & 1) {
  1462.         SAVE_NUM_OR_TIME(fp, min, axis);
  1463.     }
  1464.     putc(':', fp);
  1465.     if (autosc & 2) {
  1466.         SAVE_NUM_OR_TIME(fp, max, axis);
  1467.     }
  1468.     fputs("] )", fp);
  1469.     }
  1470.     putc('\n', fp);
  1471. }
  1472.  
  1473. /* check user defined format strings for valid double conversions */
  1474. TBOOLEAN valid_format(format)
  1475. const char *format;
  1476. {
  1477.     for (;;) {
  1478.     if (!(format = strchr(format, '%')))    /* look for format spec  */
  1479.         return TRUE;    /* passed Test           */
  1480.     do {            /* scan format statement */
  1481.         format++;
  1482.     } while (strchr("+-#0123456789.", *format));
  1483.  
  1484.     switch (*format) {    /* Now at format modifier */
  1485.     case '*':        /* Ignore '*' statements */
  1486.     case '%':        /* Char   '%' itself     */
  1487.         format++;
  1488.         continue;
  1489.     case 'l':        /* Now we found it !!! */
  1490.         if (!strchr("fFeEgG", format[1]))    /* looking for a valid format */
  1491.         return FALSE;
  1492.         format++;
  1493.         break;
  1494.     default:
  1495.         return FALSE;
  1496.     }
  1497.     }
  1498. }
  1499.